package com.gaofans.vertx.boot.web.handler;

import com.gaofans.vertx.boot.web.annotation.HttpHandler;
import io.vertx.core.Handler;
import io.vertx.ext.web.RoutingContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;

/**
 * http handler查找
 * @author GaoFans
 */
public class DefaultHttpHandlerDiscoverer implements ApplicationContextAware,HttpHandlerDiscoverer {

    private ApplicationContext applicationContext;
    private HttpHandlerChain handlerChain;
    private static final Logger LOG = LoggerFactory.getLogger(DefaultHttpHandlerDiscoverer.class);

    @Override
    public synchronized HttpHandlerChain findHttpHandlers() {
        if(handlerChain != null){
            return handlerChain;
        }
        //注解查找
        String[] beanNames = this.applicationContext.getBeanNamesForAnnotation(HttpHandler.class);
        HttpHandlerChain chain = new HttpHandlerChain();
        for (String beanName : beanNames) {
            Handler<RoutingContext> handler = this.applicationContext.getBean(beanName, Handler.class);
            HttpHandler annotation = this.applicationContext.findAnnotationOnBean(beanName, HttpHandler.class);
            if(annotation != null){
                HttpHandlerDefinition definition = new HttpHandlerDefinition();
                definition.setName(beanName);
                definition.setPath(annotation.path());
                definition.setHandler(handler);
                definition.setOrder(annotation.order());
                definition.setPosition(annotation.position());
                chain.add(definition);
                LOG.debug("找到HttpHandler: name[{}],patterns[{}]",beanName, String.join(",", definition.getPath()));
            }
        }
        //接口查找
        beanNames = this.applicationContext.getBeanNamesForType(HttpHandlerConfigurable.class);
        for (String beanName : beanNames) {
            Object bean = this.applicationContext.getBean(beanName);
            try {
                if(this.applicationContext.findAnnotationOnBean(beanName, HttpHandler.class) == null){
                    Handler<RoutingContext> handler = (Handler<RoutingContext>) bean;
                    HttpHandlerDefinition definition = new HttpHandlerDefinition();
                    HttpHandlerConfigurable configurable = (HttpHandlerConfigurable) handler;
                    definition.setName(beanName);
                    definition.setPath(configurable.getPath());
                    definition.setHandler(handler);
                    definition.setOrder(configurable.getOrder());
                    definition.setPosition(configurable.getPosition());
                    chain.add(definition);
                    LOG.debug("找到HttpHandler: name[{}],patterns[{}]",beanName, String.join(",", definition.getPath()));
                }
            }catch (Exception e){
                continue;
            }
        }
        handlerChain = chain;
        return chain;
    }

    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
